home *** CD-ROM | disk | FTP | other *** search
- /* $Header: /usr/people/sam/fax/faxd/RCS/Class20.c++,v 1.8 1994/04/25 16:10:06 sam Rel $ */
- /*
- * Copyright (c) 1994 Sam Leffler
- * Copyright (c) 1994 Silicon Graphics, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that (i) the above copyright notices and this permission notice appear in
- * all copies of the software and related documentation, and (ii) the names of
- * Sam Leffler and Silicon Graphics may not be used in any advertising or
- * publicity relating to the software without the specific, prior written
- * permission of Sam Leffler and Silicon Graphics.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
- * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
- */
- #include "Class20.h"
- #include "ModemConfig.h"
-
- #include <stdlib.h>
- #include <ctype.h>
-
- Class20Modem::Class20Modem(FaxServer& s, const ModemConfig& c) : Class2Modem(s,c)
- {
- serviceType = SERVICE_CLASS20;
- setupDefault(classCmd, conf.class2Cmd, "+FCLASS=2.0");
- setupDefault(mfrQueryCmd, conf.mfrQueryCmd, "+FMI?");
- setupDefault(modelQueryCmd, conf.modelQueryCmd, "+FMM?");
- setupDefault(revQueryCmd, conf.revQueryCmd, "+FMR?");
- setupDefault(dccQueryCmd, conf.class2DCCQueryCmd, "+FCC=?");
- setupDefault(abortCmd, conf.class2AbortCmd, "KS");
-
- setupDefault(borCmd, conf.class2BORCmd, "BO=0");
- setupDefault(tbcCmd, conf.class2TBCCmd, "PP=0");
- setupDefault(crCmd, conf.class2CRCmd, "CR=1");
- setupDefault(phctoCmd, conf.class2PHCTOCmd, "CT=30");
- setupDefault(bugCmd, conf.class2BUGCmd, "BU=1");
- setupDefault(lidCmd, conf.class2LIDCmd, "LI");
- setupDefault(dccCmd, conf.class2DCCCmd, "CC");
- setupDefault(disCmd, conf.class2DISCmd, "IS");
- setupDefault(cigCmd, conf.class2CIGCmd, "PI");
- setupDefault(splCmd, conf.class2SPLCmd, "SP");
-
- // ignore procedure interrupts
- setupDefault(pieCmd, conf.class2PIECmd, "IE=0");
- // enable reporting of everything
- setupDefault(nrCmd, conf.class2NRCmd, "NR=1,1,1,1");
- }
-
- Class20Modem::~Class20Modem()
- {
- }
-
- ATResponse
- Class20Modem::atResponse(char* buf, long ms)
- {
- if (FaxModem::atResponse(buf, ms) == AT_OTHER &&
- (buf[0] == '+' && buf[1] == 'F')) {
- if (strneq(buf, "+FHS:", 5)) {
- processHangup(buf+5);
- lastResponse = AT_FHNG;
- } else if (strneq(buf, "+FCO", 4))
- lastResponse = AT_FCON;
- else if (strneq(buf, "+FPO", 4))
- lastResponse = AT_FPOLL;
- else if (strneq(buf, "+FVO", 4))
- lastResponse = AT_FVO;
- else if (strneq(buf, "+FIS:", 5))
- lastResponse = AT_FDIS;
- else if (strneq(buf, "+FNF:", 5))
- lastResponse = AT_FNSF;
- else if (strneq(buf, "+FCI:", 5))
- lastResponse = AT_FCSI;
- else if (strneq(buf, "+FPS:", 5))
- lastResponse = AT_FPTS;
- else if (strneq(buf, "+FCS:", 5))
- lastResponse = AT_FDCS;
- else if (strneq(buf, "+FNS:", 5))
- lastResponse = AT_FNSS;
- else if (strneq(buf, "+FTI:", 5))
- lastResponse = AT_FTSI;
- else if (strneq(buf, "+FET:", 5))
- lastResponse = AT_FET;
- }
- return (lastResponse);
- }
-
- /*
- * Abort a data transfer in progress.
- */
- void
- Class20Modem::abortDataTransfer()
- {
- char c = CAN;
- putModemData(&c, 1);
- }
-
- /*
- * Send a page of data using the ``stream interface''.
- */
- fxBool
- Class20Modem::sendPage(TIFF* tif)
- {
- fxBool rc = TRUE;
- protoTrace("SEND begin page");
- if (flowControl == FLOW_XONXOFF)
- setXONXOFF(FLOW_XONXOFF, FLOW_NONE, ACT_FLUSH);
- /*
- * Correct bit order of data if not what modem expects.
- */
- u_short fillorder;
- TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
- const u_char* bitrev = TIFFGetBitRevTable(fillorder != conf.sendFillOrder);
-
- u_long* stripbytecount;
- (void) TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbytecount);
- for (u_int strip = 0; strip < TIFFNumberOfStrips(tif) && rc; strip++) {
- u_int totbytes = (u_int) stripbytecount[strip];
- if (totbytes > 0) {
- u_char* data = new u_char[totbytes];
- if (TIFFReadRawStrip(tif, strip, data, totbytes) >= 0) {
- /*
- * Pass data to modem, filtering DLE's and
- * being careful not to get hung up.
- */
- beginTimedTransfer();
- rc = putModemDLEData(data, totbytes, bitrev, getDataTimeout());
- endTimedTransfer();
- protoTrace("SENT %d bytes of data", totbytes);
- }
- delete data;
- }
- }
- if (!rc)
- abortDataTransfer();
- if (flowControl == FLOW_XONXOFF)
- setXONXOFF(FLOW_CURRENT, FLOW_XONXOFF, ACT_DRAIN);
- protoTrace("SEND end page");
- return (rc);
- }
-
- /*
- * Handle the page-end protocol.
- */
- fxBool
- Class20Modem::pageDone(u_int ppm, u_int& ppr)
- {
- static char ppmCodes[3] = { 0x2C, 0x3B, 0x2E };
- char eop[2];
- fxBool seenHangup = FALSE;
-
- eop[0] = DLE;
- eop[1] = ppmCodes[ppm];
-
- ppr = 0; // something invalid
- if (putModemData(eop, sizeof (eop))) {
- for (;;) {
- switch (atResponse(rbuf, conf.pageDoneTimeout)) {
- case AT_OK: // page data good
- case AT_ERROR: // page data bad
- if (seenHangup) {
- /*
- * Cannot query modem for post-page
- * response after hangup, so simulate
- * it here.
- */
- ppr = PPR_MCF;
- } else {
- fxStr ps;
- if (atQuery("+FPS?", ps, 500))
- ppr = atoi(ps);
- }
- return (TRUE);
- case AT_FHNG:
- if (!isNormalHangup())
- return (FALSE);
- seenHangup = TRUE;
- break;
- case AT_EMPTYLINE:
- case AT_TIMEOUT:
- case AT_NOCARRIER:
- case AT_NODIALTONE:
- case AT_NOANSWER:
- goto bad;
- }
- }
- }
- bad:
- processHangup("50"); // Unspecified Phase D error
- return (FALSE);
- }
-
- /*
- * Receive DLE-escaped data from the modem.
- */
- fxBool
- Class20Modem::recvPageDLEData(TIFF* tif)
- {
- fxBool prematureEOF = FALSE;
- u_char buf[16*1024];
- int n = 0;
- for (;;) {
- int b = getModemDataChar();
- if (b == EOF) {
- protoTrace("RECV: premature EOF");
- prematureEOF = TRUE;
- break;
- }
- if (b == DLE) {
- b = getModemDataChar();
- if (b == EOF || b == ETX) {
- if (b == EOF) {
- prematureEOF = TRUE;
- protoTrace("RECV: premature EOF");
- }
- break;
- }
- if (b != DLE) {
- if (n == sizeof (buf))
- recvData(tif, buf, sizeof (buf)), n = 0;
- buf[n++] = DLE;
- // Class 2.0 requires <DLE><SUB> be converted to <DLE><DLE>
- if (b == SUB)
- b = DLE;
- }
- }
- if (n == sizeof (buf))
- recvData(tif, buf, sizeof (buf)), n = 0;
- buf[n++] = b;
- }
- if (n > 0)
- recvData(tif, buf, n);
- return (prematureEOF);
- }
-